#ifndef TYPEDEF
#define TYPEDEF

#include <map>
#include <array>
#include <tuple>
#include <cstring>
#include <cstdint>
#include <shared_mutex>

// 枚举值定义
enum REGVAL
{
	Code,
	Cause,
	Status,
	IE,
	IT,
	IDTR,
	PDTR = 7,
	RetAddr = 11,
	Stack = 14
};
enum FLAG
{
	Zero = 1,
	Pos = 2,
	Neg = 4,
	IntEN = 1 << 8,
	IntTR = 1 << 9,
	Priv = 1 << 10,
	Error = 1 << 16,
	Halt = 1 << 17,
	CacheEN = 1 << 18,
	TLB_EN = 1 << 19,
	PageEN = 1 << 20
};
enum ACCESS
{
	R = 1,	// 读
	W = 2,	// 写
	X = 4,	// 执行
	P = 8,	// 特权值
	IO = 16 // IO操作
};
enum IOSTATUS : uint8_t
{
	READY = 0,
	DONE = 1,
	READ,
	WRITE,
	SET0 = 0x10,
	SET1 = 0x11,
	GET0 = 0x20,
	GET1 = 0x21,
	SHUTDOWN = 0x80,
	FAIL = 0xff
};

class Mutex
{
private:
	bool locker;

public:
	Mutex() : locker(true) {}
	void lock()
	{
		while (locker)
			;
		locker = true;
	}
	void unlock()
	{
		locker = false;
	}
	bool try_lock()
	{
		if (locker == false)
		{
			locker = true;
			return true;
		}
		return false;
	}
};

template <typename T>
class Semaphore
{
private:
	std::shared_mutex mtx;
	T value;

public:
	Semaphore() = default;
	Semaphore &operator=(const Semaphore &other)
	{
		this->value = other.value;
		return *this;
	}
	void rlock()
	{
		mtx.lock_shared();
	}
	void r_unlock()
	{
		mtx.unlock_shared();
	}
	void w_lock()
	{
		mtx.lock();
	}
	void w_unlock()
	{
		mtx.unlock();
	}
	inline T &get() { return value; }
};

template <typename T>
struct pairs
{
	std::shared_ptr<T> first, second;
	T &operator[](const bool label) { return label ? *second : *first; }
};

class MessageBus // 提供片上消息通讯
{
public:
	std::array<pairs<uint64_t>, 8> sregs;
	Mutex cMAR, cMDR, tMAR, dMAR, dMDR, needLoad, done;
	uint64_t MAR, MDR;
	uint16_t size;
	uint16_t access;
	bool priv, fresh;

	MessageBus() : MAR(0), MDR(0), size(0), access(0), priv(true), fresh(false)
	{
		for (int i = 0; i < 8; i++)
			sregs[i].first = std::make_shared<uint64_t>(0);
		sregs[Code].second = std::make_shared<uint64_t>(0);
		sregs[IE].second = std::make_shared<uint64_t>(0);
		sregs[IT].second = std::make_shared<uint64_t>(0);
		sregs[Cause].second = sregs[Cause].first;
		sregs[Status].second = sregs[Status].first;
		sregs[IDTR].second = sregs[IDTR].first;
		sregs[6].second = sregs[6].first;
		sregs[PDTR].second = sregs[PDTR].first;
	}
	MessageBus &operator=(const MessageBus &other)
	{
		this->sregs = other.sregs;
		return *this;
	}
};
struct IOMessage
{
	Mutex start, end; // 用于同步IO操作
	uint64_t addr;	  // 地址
	uint16_t port;	  // 端口号，用于IO通道选择
	bool shutdown;	  // 用于IO控制机关机
	bool isData;	  // true表示数据，false表示控制信号
	bool dir;		  // 读写方向，true表示离开IO，false表示前往IO
};

#endif